package cn.flant.io.tools;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import cn.flant.log.Logger;

public class MultiConnector {
	public static final int TCP = 0;
	public static final int UDP = 1;

	private Logger log = Logger.getLogger(MultiConnector.class);
	private Map<String, Connector> connectorMap = new ConcurrentHashMap<String, Connector>();
	private Connector[] connectors = new Connector[0];
	private Charset charset;
	private boolean enableCache;
	private int cacheSize;

	public MultiConnector() {
		enableCache = true;
		cacheSize = 5120;
	}

	private synchronized void initConnectorArray() {
		connectors = connectorMap.values().toArray(new Connector[connectorMap.size()]);
	}

	public void setCharset(Charset charset) {
		this.charset = charset;
		for (Connector conn : connectors) {
			conn.setCharset(charset);
		}
	}

	public boolean isEnableCache() {
		return enableCache;
	}

	public void setEnableCache(boolean enableCache) {
		this.enableCache = enableCache;
		for (Connector conn : connectors) {
			conn.setEnableCache(enableCache);
		}
	}

	public int getCacheSize() {
		return cacheSize;
	}

	public void setCacheSize(int cacheSize) {
		this.cacheSize = cacheSize;
		for (Connector conn : connectors) {
			conn.setCapacity(cacheSize);
		}
	}

	public Charset getCharset() {
		return charset;
	}

	public synchronized boolean addConnector(int type, String host, int port) {
		String key = host + ":" + port;
		if (connectorMap.containsKey(key)) {
			log.debug(key + " is added");
			return false;
		}
		Connector conn = null;
		switch (type) {
		case TCP:
			conn = new TcpConnector(host, port);
			break;
		case UDP:
			conn = new UdpConnector(host, port);
			break;
		default:
			log.debug("unknown connector type: " + type + ", dest: " + key);
			return false;
		}
		conn.setEnableCache(enableCache);
		conn.setCapacity(cacheSize);
		conn.setCharset(charset);
		connectorMap.put(key, conn);
		initConnectorArray();
		return true;
	}

	public synchronized boolean removeConnector(String host, int port) {
		String key = host + ":" + port;
		Connector conn = connectorMap.remove(key);
		if (conn != null) {
			initConnectorArray();
			conn.destroy();
			return true;
		} else {
			return false;
		}
	}

	public boolean containsConnector(String host, int port) {
		String key = host + ":" + port;
		return connectorMap.containsKey(key);
	}

	public synchronized void removeAllConnector() {
		for (Connector conn : connectorMap.values()) {
			conn.destroy();
		}
		connectorMap.clear();
		initConnectorArray();
	}

	public synchronized List<Connector> getConnectorList() {
		return new ArrayList<Connector>(connectorMap.values());
	}

	public int getConnectorCount() {
		return connectorMap.size();
	}

	public synchronized void closeConnection() {
		for (Connector conn : connectorMap.values()) {
			conn.closeConnection();
		}
	}

	public synchronized void openConnection() {
		for (Connector conn : connectorMap.values()) {
			conn.openConnection();
		}
	}

	public void destroy() {
		removeAllConnector();
	}

	public synchronized void sendLine(String str) {
		for (Connector conn : connectorMap.values()) {
			conn.sendLine(str);
		}
	}

	public synchronized void send(String str) {
		for (Connector conn : connectorMap.values()) {
			conn.send(str);
		}
	}

	public synchronized void send(byte[] bytes) {
		for (Connector conn : connectorMap.values()) {
			conn.send(bytes);
		}
	}

	public String toString() {
		return connectorMap.keySet().toString();
	}
}
